package com.bjb.vr.server.controller;

import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import com.bjb.vr.common.ao.SyncDataAo;
import com.bjb.vr.common.constant.EncryptConstant;
import com.bjb.vr.common.dto.SyncData;
import com.bjb.vr.common.dto.SysUpgrade;
import com.bjb.vr.common.result.BaseResult;
import com.bjb.vr.common.result.CommonResult;
import com.bjb.vr.common.utils.GuavaCacheUtil;
import com.bjb.vr.server.service.DataHandlerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.concurrent.ExecutionException;

/**
 * @version 1.0.0
 * @author: HuJingBo
 * @time: 2022/7/13 12:23
 */
@Slf4j
@RestController
@RequestMapping("/api/datasync/v1")
public class DataSyncController {

    @Autowired
    DataHandlerService dataHandlerService;


    /**
     * 验证签名
     *
     * @param syncDataAo
     * @return
     */
    private boolean checkSign(SyncDataAo syncDataAo) {
        byte[] key = EncryptConstant.ENCRYPT_KEY.getBytes();
        HMac mac = new HMac(HmacAlgorithm.HmacMD5, key);
        StringBuilder builder = new StringBuilder();
        String dataInfo = builder.append(syncDataAo.getTenantId()).append(syncDataAo.getRequestId()).append(syncDataAo.getRequestTime()).toString();
        String macHex = mac.digestHex(dataInfo);
        return macHex.equals(syncDataAo.getSignature());
    }

    /**
     * 接受本地同步数据[客户端->服务端]
     *
     * @param syncDataAo
     * @return
     */
    @PostMapping("/sendSyncData")
    public BaseResult sendSyncData(@RequestBody SyncDataAo syncDataAo) throws ExecutionException {
        // 1、验证签名
        boolean checkSign = checkSign(syncDataAo);
        if (!checkSign) {
            return CommonResult.Fail("签名验证失败");
        }

        // 2、验证该租户是否再同步表【sys_tenant】中存在
        String tenantId = syncDataAo.getTenantId();
        List<String> tenants = GuavaCacheUtil.getTenantCache().get(tenantId);
        if (!tenants.contains(tenantId)) {
            log.info("租户【{}】不在云端同步表中,请确认！", tenantId);
            return CommonResult.Fail("租户【" + tenantId + "】不在云端同步表中,请联系管理员！");
        }

        // 3、同步数据
        dataHandlerService.sendSyncData(syncDataAo);
        return CommonResult.Ok("已接收到同步数据");
    }

    /**
     * 查询云端同步数据[服务端->客户端]
     *
     * @param syncDataAo
     * @return
     */
    @PostMapping("/getSyncData")
    public BaseResult queryCloudData(@RequestBody SyncDataAo syncDataAo) {
        // 1、验证签名
        boolean checkSign = checkSign(syncDataAo);
        if (!checkSign) {
            return CommonResult.Fail("签名验证失败");
        }
        // 2、查询数据
        List<SyncData> cloudData = dataHandlerService.queryCloudData(syncDataAo);
        return CommonResult.Ok().setResult(cloudData);
    }

    /**
     * 删除云端同步到本地完成之后数据
     *
     * @param syncDataAo
     * @return
     */
    @PostMapping("/removeSyncData")
    public BaseResult removeSyncData(@RequestBody SyncDataAo syncDataAo) {
        // 1、验证签名
        boolean checkSign = checkSign(syncDataAo);
        if (!checkSign) {
            return CommonResult.Fail("签名验证失败");
        }
        // 2、删除数据
        boolean result = dataHandlerService.removeSyncData(syncDataAo);
        if (!result) {
            return CommonResult.Fail("删除同步数据失败！");
        }
        return CommonResult.Ok("删除同步数据成功！");
    }

    /**
     * 获取需要升级的数据
     *
     * @param syncDataAo
     * @return
     */
    @PostMapping("/getUpgradeInfo")
    public BaseResult getUpgradeInfo(@RequestBody SyncDataAo syncDataAo) {
        // 1、验证签名
        boolean checkSign = checkSign(syncDataAo);
        if (!checkSign) {
            return CommonResult.Fail("签名验证失败");
        }
        // 2、请求数据
        List<SysUpgrade> upgradeList = dataHandlerService.getUpgradeInfo(syncDataAo);
        return CommonResult.Ok().setResult(upgradeList);
    }

}
